﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace SurvivalStrategy.WorldData
{
    public class WorldChunk
    {
        public Vector2 position;                                            //pozycja globalna chunka
        private static int width = 10;                                       //ilosc klockow w szerokisci chunka
        private static int height = 10;                                      //ilosc klockow w wysokosci chunka
        public static int CellWidth = 16;                                   //wysokosc i szerokosc jeden komorki
        public static int CellHeight = 16;
        public static int Width { get { return CellWidth * width; } }       //szerokosc chunka
        public static int Height { get { return CellHeight * height; } }    //wysokosc chunka

        public Dictionary<int, WorldElement> ChunkElements { get; internal set; }   // slownik zawierajacy wszystkie elementy w chunku, 
                                                                                    // pozwala na szybka komunikacje z elementem uzywajac id elementu
        public int ID { get; internal set; }

        private List<WorldElement>[,] chunkData;                            //zbior wszystkich elementow w konkrentnym chunku
        public List<WorldElement>[,] ChunkData { get { return chunkData; } }

        public WorldChunk(int id, Vector2 position)
        {
            chunkData = new List<WorldElement>[width, height];
            ChunkElements = new Dictionary<int, WorldElement>();
            this.ID = id;
            this.position = position;
            for (int i = 0; i < chunkData.GetLength(0); i++)
                for (int j = 0; j < chunkData.GetLength(1); j++)
                    chunkData[i, j] = new List<WorldElement>();
        }

        public void AddElement(WorldElement element)
        {
            ChunkElements.Add(element.ID, element);
            element.SetChunkOwner(this);
            //pamietaj o lokalnej pozycji elementu
            //dodac referencje do elemetu we wszystkich komorkach przez ktore przechodzi element
            Vector3 localElementPosition = new Vector3(element.Position.X - position.X*Width, element.Position.Y, element.Position.Z - position.Y*Height);
            //Vector2 posRightUpPoint = new Vector2((float)width * (float)Math.Cos(element.Rotation.X) - 0, (float)width * (float)Math.Sin(element.Rotation.X) + 0);
            //Vector2 posRigtDownPoint = new Vector2((float)width * (float)Math.Cos(element.Rotation.X) - (float)height * (float)Math.Sin(element.Rotation.X), (float)width * (float)Math.Sin(element.Rotation.X) + (float)height * (float)Math.Cos(element.Rotation.X));
            //Vector2 posLeftDownPoint = new Vector2(0 - (float)height * (float)Math.Sin(element.Rotation.X), 0 + (float)height * (float)Math.Cos(element.Rotation.X));
            /*for(int i = 0; i < (int)element.Size.X; i++)
                for (int j = 0; j < (int)element.Size.Y; j++)
                {
                    chunkData[(int)localElementPosition.X/CellWidth + i, (int)localElementPosition.Y/CellHeight + j].Add(element);
                }*/


            float tempX = ((float)localElementPosition.X / (float)CellWidth);
            float tempY = ((float)localElementPosition.Z / (float)CellHeight);
            float sizeX = (float)(element.Size.X/CellWidth);
            float sizeZ = (float)(element.Size.Z/CellWidth);
            float cosX = (float)Math.Cos(-element.Rotation.X);
            float sinX = (float)Math.Sin(-element.Rotation.X);

            for (int i = (int)tempX; i < chunkData.GetLength(0); i++)
                for (int j = (int)tempY; j < chunkData.GetLength(1); j++)
                {
                    Vector2 tempElementPosition = new Vector2((float)i - tempX, (float)j - tempY); //Liczy punkt przesunięty o lokalną pozycję badanego
                    
                    Vector2 rightDownPoint = new Vector2(
                        tempElementPosition.X * cosX - tempElementPosition.Y * sinX,
                        tempElementPosition.X * sinX + tempElementPosition.Y * cosX); // przelicza na układ, w którym można go porównać do nieporuszonego prostokąta

                    if (rightDownPoint.X < sizeX && rightDownPoint.X >= 0 && rightDownPoint.Y < sizeZ && rightDownPoint.Y>= 0)
                    {
                        int x = (int)tempX + (int)tempElementPosition.X;
                        int y = (int)tempY + (int)tempElementPosition.Y;
                        element.SetOwner(chunkData[x,y]);
                        chunkData[x,y].Add(element); // sprawdza czy punkt zawiera się w nieprzesuniętym prostokącie.
                    }
                }
        }

        public List<WorldElement> GetWorldElements(Vector3 v)
        {
            Vector3 localElementPosition = new Vector3(v.X - position.X*Width, v.Y, v.Z - position.Y*Height);
            return chunkData[(int)(localElementPosition.X / CellWidth), (int)(localElementPosition.Z / CellHeight)];
        }

        public void RemoveElement(Vector3 v, WorldElement element)
        {
            if(GetWorldElements(v).Contains(element))
                GetWorldElements(v).Remove(element);
        }
    }
}
